#!/usr/bin/env python3
import sys
import socket
import random
from scapy.all import sendp, get_if_list, get_if_hwaddr
from scapy.all import Ether, IP, UDP, TCP


class NetworkSender:
    """Utility for sending TCP/UDP network packets"""
    
    def __init__(self):
        self.iface = self._get_network_interface()
    
    def _get_network_interface(self):
        """Find first available Ethernet interface with 'eth0'"""
        interfaces = [iface for iface in get_if_list() if "eth0" in iface]
        if not interfaces:
            print("No eth0 interface available")
            sys.exit(1)
        return interfaces[0]
    
    def build_packet(self, target_ip, proto, target_port, payload):
        """Construct a TCP or UDP packet with given parameters"""
        base_frame = Ether(src=get_if_hwaddr(self.iface), dst='ff:ff:ff:ff:ff:ff') / IP(dst=target_ip)
        src_port = random.randint(49152, 65535)  # Ephemeral port range
        
        if proto == "TCP":
            return base_frame / TCP(dport=target_port, sport=src_port) / payload
        else:
            return base_frame / UDP(dport=target_port, sport=src_port) / payload
    
    def transmit(self, target_ip, proto, target_port, payload):
        """Send constructed packet through the network interface"""
        print(f"Transmitting on {self.iface} to {target_ip}")
        packet = self.build_packet(target_ip, proto, target_port, payload)
        packet.show2()
        sendp(packet, iface=self.iface, verbose=False)


def main():
    if len(sys.argv) < 5:
        print("Usage: python3 sender.py <destination> <TCP|UDP> <dport> <message>")
        sys.exit(1)
    
    try:
        dest_ip = socket.gethostbyname(sys.argv[1])
        protocol = sys.argv[2]
        dest_port = int(sys.argv[3])
        message = sys.argv[4]
        
        sender = NetworkSender()
        sender.transmit(dest_ip, protocol, dest_port, message)
        
    except Exception as e:
        print(f"Error occurred: {e}")
        sys.exit(1)


if __name__ == '__main__':
    main()